#include "Player.h"
#include "FileSave.h"
#include "ChallengeModeDecorator.h"

// 角色赋值
Player::Player(CSrRef name)
{
    // 人物参数
    this->SetName(name);
    this->SetSymbol("🧙‍");
    this->SetAttack(10);
    this->SetHP(100);
    this->SetDefind(1);

    // 坐标
    this->Getpoint().Setx(0);
    this->Getpoint().Sety(0);
    this->SetMaxHeight(HEIGHT);
    this->SetMaxWidth(WIDTH);
    // 金钱 经验
    this->SetGloden(100);
    this->SetExp(0);
    this->SetLevel(0);
    // 点数初始化
    this->SetAttrPoint(5);
    // 武器初始化
    w = nullptr;
    a = nullptr;
    this->SetcritChance(0.5);
    this->SetdodgeChance(0.5);
}

// 角色移动
void Player::Move(std::shared_ptr<Scene>& s,std::shared_ptr<Scene>& s1,std::shared_ptr<Scene>& s2,std::shared_ptr<Scene>& s3)
{

    ChallengeModeDecorator challenge;
    static int count = 0;
    FileSave &fileSave = FileSave::getInstance(); // 在 switch 语句外部声明
    fileSave.userName = GetName();
    std::cout << "请输入角色移动(w:上 s:下 a:左 d:右 p:分配个人属性 b:查看背包 f:存档 r:读档 c:挑战模式 l:退出 n:传送到下一层 m:传送到上一层):";
    char choice = -1;
    std::cin >> choice;
    while (getchar() != '\n')
        ;
    switch (choice)
    {
    case 'w':
        up();
        break;

    case 's':
        down();

        if (getPoint()->Gety() >= MaxHeight)
        {
            getPoint()->Sety(MaxHeight - 1);
        }
        break;

    case 'a':
        left();
        break;

    case 'd':
        right();
        // 防止走出边界
        if (getPoint()->Getx() >= MaxWidth)
        {
            getPoint()->Setx(MaxWidth - 1);
        }
        break;
    case 'p':
        AttrInterface();
        break;
    case 'b':
        showBag();
        break;
    case 'f':
    {
        std::cout << "请选择第几个存档:1 2 3" << std::endl;
        int i = 0;
        std::cin >> i;

        fileSave.savePlayer(std::to_string(i));
        fileSave.saveMonster(std::to_string(i));
        fileSave.saveTreasure(std::to_string(i));
        fileSave.saveBag(std::to_string(i));
    }
    break;
    case 'r':
    {
        std::cout << "请选择第几个存档:1 2 3" << std::endl;
        int i = 0;
        std::cin >> i;
        fileSave.readPlayer(std::to_string(i));
        fileSave.readMonster(std::to_string(i));
        fileSave.readTreasure(std::to_string(i));
        fileSave.readBag(std::to_string(i));
    }
    break;
    case 'c':
        fileSave.s = challenge.Challenge(fileSave.s);
        break;
    case 'l':
        exit(1);
        break;
    case 'n':
    {
        count++;
        
        if (count == 1)
        {
            s=s2;
        }
        else if (count == 2)
        {
           s=s3;
        }
        else if (count >= 3)
        {
            std::cout << "逃出魔塔，获得胜利" << std::endl;
            sleep(3);
            exit(1);

        }
       
    }
    break;
    case 'm':
    {
        count--;
        if(count==0)
        {
            s=s1;
        }
        if (count == 1)
        {
            s=s2;
        }
        else if (count == 2)
        {
            s=s3;
        }
        else if (count >= 3)
        {
            std::cout << "逃出魔塔，获得胜利" << std::endl;
            sleep(3);
            exit(1);
        }
        if(count<0)
        {
            std::cout<<"已经到了最下层"<<std::endl;
            count=0;
            sleep(3);
        }
       
    }
    break;
    default:
        break;
    }
}

void Player::LevelUp()
{
    if (GetExp() >= 100)
    {
        SetExp(GetExp() - 100);
        Level++;
        // 升级经验每级增加
        AttrPoint += 5;
        std::cout << "恭喜升级！升级到 " << Level << " 级" << std::endl;
    }
}

std::vector<PropPtr> &Player::Getbag()
{
    return bag;
}

// 装备显示(怎么知道武器/药品)
void Player::showBag()
{
    while (1)
    {
        std::cout << "========背包========\n"
                  << std::endl;
        int i = 0;
        for (; i < bag.size(); i++)
        {
            std::cout << i + 1 << "、";
            bag[i]->show(); // 多态 调子类
        }
        std::cout << i + 1 << "、" << "退出" << std::endl;
        std::cout << "请选择你要操作的物品" << std::endl;
        int choice = 0;
        std::cin >> choice;
        if (std::cin.fail())
        {
            // 清除错误标志
            std::cin.clear();
            // 丢弃错误的输入
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cout << "输入非法，请重新输入: \n";
            continue;
        }
        if (choice < 0 || choice > i + 1)
        {
            std::cout << "输入非法，请重新输入: \n";
            continue;
        }
        if (choice == i + 1)
        {
            return;
        }
        // 判断是武器 还是 药品
        // 语句初始化

        if (auto ptr = dynamic_cast<Weapon *>(bag[choice - 1].get()); ptr != nullptr && ptr->Getattribute() == "武器")
        {
            // 装备武器
            std::cout << "是否确定要更换武器？(y/n)";
            char c = 0;
            std::cin >> c;
            if (c == 'y' || c == 'Y')
            {
                if (w)
                {
                    std::cout << "卸下 " << w->GetName() << " " << std::endl;
                    SetAttack(GetAttack() - w->GetAttack());
                    SetdodgeChance(GetdodgeChance() - w->GetdodgeChance());
                    SetcritChance(GetcritChance() - w->GetcritChance());
                }
                w = ptr; // 用的时候 用裸指针
                std::cout << "装备 " << w->GetName() << " " << std::endl;
                SetAttack(GetAttack() + w->GetAttack());
                SetcritChance(std::min(GetcritChance() + w->GetcritChance(), static_cast<float>(1.0)));
                SetdodgeChance(std::min(GetdodgeChance() + w->GetdodgeChance(), static_cast<float>(0.5)));
                sleep(1);
            }
        }
        else if (auto ptr = dynamic_cast<Potion *>(bag[choice - 1].get()); ptr != nullptr && ptr->Getattribute() == "药品")
        {
            std::cout << "使用 " << ptr->GetName() << " " << std::endl;
            SetHP(std::min(GetHP() + ptr->GetHealAmount(), 100));
            std::cout << "当前血量：" << GetHP() << std::endl;
            // std::swap(bag[choice-1], bag[bag.size() - 1]); //将要删除的元素交换到最后
            // bag.pop_back();
            PopBag(choice);
        }
        else if (auto ptr = dynamic_cast<Armor *>(bag[choice - 1].get()); ptr != nullptr && ptr->Getattribute() == "防具")
        {
            // 装备防具
            std::cout << "是否确定要更换防具？(y/n)";
            char c = 0;
            std::cin >> c;
            if (c == 'y' || c == 'Y')
            {
                if (a)
                {
                    std::cout << "卸下 " << a->GetName() << " " << std::endl;
                    SetDefind(GetDefind() - a->GetDefense());
                    SetdodgeChance(GetdodgeChance() - a->GetdodgeChance());
                }
                a = ptr; // 用的时候 用裸指针
                std::cout << "装备 " << a->GetName() << " " << std::endl;
                SetdodgeChance(std::min(GetdodgeChance() + a->GetdodgeChance(), static_cast<float>(0.5)));
                sleep(1);
            }
        }
    }
}

// 属性点的加成
void Player::AttrInterface()
{
    while (1)
    {
        system("clear");
        std::cout << "当前可分配的属性点是： " << AttrPoint << std::endl;
        std::cout << "1、血量: " << GetHP() << std::endl;
        std::cout << "2、攻击力: " << GetAttack() << std::endl;
        std::cout << "3、防御力: " << GetDefind() << std::endl;
        std::cout << "4、退出: " << std::endl;

        int choice = 0;
        int number;
        std::cout << "请选择你要分配的属性: ";
        std::cin >> choice;
        if (std::cin.fail())
        {
            // 清除错误标志
            std::cin.clear();
            // 丢弃错误的输入
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cout << "输入非法，请重新输入: \n";
            continue;
        }
        if (choice < 0 || choice > 4)
        {
            std::cout << "输入非法，请重新输入: \n";
            continue;
        }
        if (choice == 4)
        {
            return;
        }
        std::cout << "请选择你要添加的数量: ";
        std::cin >> number;
        while (number > AttrPoint || number < 0)
        {
            std::cout << "分配点数超过最大可分配属性点 请重新选择!";
            std::cin >> number;
            sleep(1);
        }
        AttrPoint -= number;
        switch (choice)
        {
        case 1:
            SetHP(GetHP() + number);
            break;

        case 2:
            // std::cout << GetAttack() << " " << number <<std::endl;
            SetAttack(GetAttack() + number);
            break;

        case 3:
            SetDefind(GetDefind() + number);
            break;

        default:
            break;
        }
        std::cout << "分配成功\n";
    }
}

// 打印角色信息
void Player::show()
{
    std::cout << "玩家姓名: " << GetName() << std::endl;
    std::cout << "血量❤ : " << GetHP() << std::endl;
    std::cout << "攻击力⚔️ : " << GetAttack() << std::endl;
    std::cout << "防御力🛡 : " << GetDefind() << std::endl;
    std::cout << "暴击概率：" << GetcritChance() << std::endl;
    std::cout << "闪避概率:" << GetdodgeChance() << std::endl;

    std::cout << "等级： " << GetLevel() << " " << "经验值 " << GetExp() << " " << std::endl;
    std::cout << "金钱： " << GetGloden() << " " << std::endl;
    if (w)
    {
        std::cout << "武器: " << w->GetName() << " " << std::endl;
    }
    if (a != nullptr)
    {
        std::cout << "防具：" << a->GetName() << " " << std::endl;
    }
}

// 背包
void Player::InsertBag(const PropPtr &ptr)
{
    bag.push_back(ptr->clone());
}
void Player::PopBag(int i)
{
    std::swap(bag[i - 1], bag[bag.size() - 1]); // 将要删除的元素交换到最后
    bag.pop_back();
}

int Player::BagSize()
{
    return bag.size();
}

Weapon *Player::getWeapon()
{
    return w;
}
Armor *Player::getArmor()
{
    return a;
}